package com.atguigu.service.Impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.common.exception.YyghException;
import com.atguigu.config.HttpRequestHelper;
import com.atguigu.config.MqConst;
import com.atguigu.mapper.OrderInfoMapper;
import com.atguigu.service.OrderService;
import com.atguigu.service.RabbitService;
import com.atguigu.service.WeiXinService;
import com.atguigu.yygh.enums.OrderStatusEnum;
import com.atguigu.yygh.hosp.client.HospitalFeignClient;
import com.atguigu.yygh.model.order.OrderInfo;
import com.atguigu.yygh.model.user.Patient;
import com.atguigu.yygh.user.client.PatientFeignClient;
import com.atguigu.yygh.vo.hosp.ScheduleOrderVo;
import com.atguigu.yygh.vo.msm.MsmVo;
import com.atguigu.yygh.vo.order.OrderCountQueryVo;
import com.atguigu.yygh.vo.order.OrderCountVo;
import com.atguigu.yygh.vo.order.OrderMqVo;
import com.atguigu.yygh.vo.order.OrderQueryVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrderServiceImpl extends ServiceImpl<OrderInfoMapper,OrderInfo> implements  OrderService{
   @Autowired
    PatientFeignClient  patientFeignClient;
    @Autowired
    HospitalFeignClient  hospitalFeignClient;
    @Autowired
    private RabbitService rabbitService;

    @Override
    public Long saveOrder(String scheduleId, Long patientId) {
     //查看排班（医院服务 +查询就诊人）
        //0 查询数据 为调用医院端接口做准备
        Patient patient = patientFeignClient.getPatientVo(patientId);
        ScheduleOrderVo scheduleOrderVo = hospitalFeignClient.getScheduleOrderVo(scheduleId);
        //2创建自己的订单
        Map<String,Object> paramMap =new HashMap<>();
        paramMap.put("hoscode",scheduleOrderVo.getHoscode());
        paramMap.put("depcode",scheduleOrderVo.getDepcode());
        paramMap.put("hosScheduleId",scheduleOrderVo.getHosScheduleId());//排班编号
        paramMap.put("reserveDate", new DateTime(scheduleOrderVo.getReserveDate()).toString(("yyyy-MM-dd")));//安排日期
        paramMap.put("reserveTime",scheduleOrderVo.getReserveTime());
        paramMap.put("amount",scheduleOrderVo.getAmount());
        //这里封装的是 patient的数据
        paramMap.put("name",patient.getName());
        paramMap.put("certificatesType",patient.getCertificatesType());
        paramMap.put("certificatesNo", patient.getCertificatesNo());
        paramMap.put("sex",patient.getSex());
        paramMap.put("birthdate", patient.getBirthdate());
        paramMap.put("phone",patient.getPhone());
        paramMap.put("isMarry", patient.getIsMarry());
        paramMap.put("provinceCode",patient.getProvinceCode());
        paramMap.put("cityCode", patient.getCityCode());
        paramMap.put("districtCode",patient.getDistrictCode());
        paramMap.put("address",patient.getAddress());
        paramMap.put("contactsName",patient.getContactsName());
        paramMap.put("contactsCertificatesType", patient.getContactsCertificatesType());
        paramMap.put("contactsCertificatesNo",patient.getContactsCertificatesNo());
        paramMap.put("contactsPhone",patient.getContactsPhone());
        paramMap.put("timestamp", HttpRequestHelper.getTimestamp());
        paramMap.put("sign", "");
        //4、调用医院端挂号接口--调用
        String apiUrl = hospitalFeignClient.apiUrl(scheduleOrderVo.getHoscode());
        String url="http://localhost:"+apiUrl+"/order/submitOrder";
        JSONObject jsonObject = HttpRequestHelper.sendRequest(paramMap, url);

        //1 调用接口成功
          if(jsonObject.getInteger("code")==200){ //挂号成功
               //拿到发送的数据  (调用医院接口成功）
              JSONObject data = jsonObject.getJSONObject("data");
              //从数据中将各个参数拿出来
              String hosRecordId = data.getString("hosRecordId");
              Integer number = data.getInteger("number");
              //从mg数据库里面查询到该排班  更新两个 number
              Integer reservedNumber = data.getInteger("reservedNumber"); //可预约数
              Integer availableNumber = jsonObject.getInteger("availableNumber");//剩余预约数
              String fetchTime = data.getString("fetchTime");
              String fetchAddress = data.getString("fetchAddress");

              //创建自己的订单
              OrderInfo  orderInfo =new OrderInfo();
              orderInfo.setUserId(patient.getUserId());

              String outTradeNo = System.currentTimeMillis()+""+new Random().nextInt(100);
              //1 设置订单编号 订单编号唯一  退款 付款都要使用
              orderInfo.setOutTradeNo(outTradeNo);
              orderInfo.setHoscode(scheduleOrderVo.getHoscode());
              orderInfo.setHosname(scheduleOrderVo.getHosname());
              orderInfo.setDepcode(scheduleOrderVo.getDepcode());
              orderInfo.setDepname(scheduleOrderVo.getDepname());
              orderInfo.setTitle(scheduleOrderVo.getTitle());
              orderInfo.setScheduleId(scheduleOrderVo.getHosScheduleId());
              orderInfo.setReserveDate(scheduleOrderVo.getReserveDate());
              orderInfo.setReserveTime(scheduleOrderVo.getReserveTime());
              //就诊人
              orderInfo.setPatientId(patient.getId()); //id
              orderInfo.setPatientName(patient.getName());//姓名
              orderInfo.setPatientPhone(patient.getPhone());//手机
              //当前平台端订单存储医院端订单的id
              orderInfo.setHosRecordId(hosRecordId);
              orderInfo.setNumber(number);//取号顺序
              orderInfo.setFetchAddress(fetchAddress);
              orderInfo.setAmount(scheduleOrderVo.getAmount()); //医疗服务费
              orderInfo.setQuitTime(scheduleOrderVo.getQuitTime()); //退号时间
              orderInfo.setOrderStatus(OrderStatusEnum.UNPAID.getStatus());
              orderInfo.setCreateTime(new Date());
              orderInfo.setUpdateTime(new Date());
              //将订单添加到数据库中
              baseMapper.insert(orderInfo);  //平台端订单
              //更新mg数据库的 排班号源数量 +给用户发送短
           //   this.afterOrder(scheduleId,availableNumber,reservedNumber,patient);
              return orderInfo.getId();
          }

        return null;
    }

    private void afterOrder(String scheduleId, Integer availableNumber, Integer reservedNumber, Patient patient) {
        //目的是给医院端发送消息
        OrderMqVo  orderMqVo =new OrderMqVo();
        orderMqVo.setScheduleId(scheduleId); //mq的排班id
        orderMqVo.setAvailableNumber(availableNumber);
        orderMqVo.setReservedNumber(reservedNumber);
        //发送消息
        MsmVo msmVo=new MsmVo();
        msmVo.setPhone(patient.getPhone());
        msmVo.getParam().put("message",patient.getName()+"您的订单已经创建成功");  //发送的内容
        orderMqVo.setMsmVo(msmVo);
         rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_ORDER,MqConst.ROUTING_ORDER,orderMqVo);
    }

    @Override
    public OrderInfo getOrderInfo(Long id) {
        //从 baseMap里面 获取订单服务
        OrderInfo orderInfo = baseMapper.selectById(id);
         return  this.packOrderInfo(orderInfo);

    }

     @Autowired
    private WeiXinService weiXinService;

    /**
     * 取消订单实现类
     * @param orderId
     * @return
     */
    @Override
    public Boolean cancelOrder(Long orderId) {
        //查看订单
        OrderInfo orderInfo = this.getById(orderId);
        //2、超过退号时间，不能取消
        DateTime  quitTime =new DateTime();
        if(quitTime.isBeforeNow()){
            throw new YyghException(20001,"退号时间已过");
        }
        //调用医院接口 将医院状态改为 -1 医院号源数量 +1
        Map<String,Object > map =new HashMap<>();
        map.put("hoscode",orderInfo.getHoscode());
        map.put("hosRecordId",orderInfo.getHosRecordId());
        JSONObject jsonObject = HttpRequestHelper.sendRequest(map, "http://localhost:9998/order/updateCancelStatus");
        if(jsonObject.getInteger("code")!=200){
            throw  new YyghException(20001,"退号失败");
        }else{
            //订单已经支付需要退款
            if(orderInfo.getOrderStatus()==OrderStatusEnum.PAID.getStatus().intValue()){
                Boolean refund = weiXinService.refund(orderId);
                if(!refund){
                    throw new YyghException(20001,"退款失败");
                }
            }
            //更改平台订单状态已取消
            orderInfo.setOrderStatus(OrderStatusEnum.CANCLE.getStatus());
            this.updateById(orderInfo); //修改数据库信息

            //向mq 发送消息  ，异步更新号源数量+短信通知
            OrderMqVo  orderMqVo =new OrderMqVo();
            orderMqVo.setScheduleId(orderInfo.getScheduleId());
            MsmVo msmVo =new MsmVo();
            msmVo.setPhone(orderInfo.getPatientPhone());
            msmVo.getParam().put("message","取消挂号成功");
            orderMqVo.setMsmVo(msmVo);
            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_ORDER,MqConst.ROUTING_ORDER,orderMqVo);
        }
        return true;
    }

    @Override
    public void patientTips() {
        //查询今天顾好
        QueryWrapper<OrderInfo> queryWrapper =new QueryWrapper<>();
        queryWrapper.eq("reserve_date",new DateTime().toString("yyyy-MM-dd"));
        List<OrderInfo> orderInfoList = baseMapper.selectList(queryWrapper);

        //2 遍历
        //2、遍历
        for(OrderInfo orderInfo : orderInfoList) {
            //短信提示
            MsmVo msmVo = new MsmVo();
            msmVo.setPhone(orderInfo.getPatientPhone());
            msmVo.getParam().put("message","请及时就医");
            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_MSM, MqConst.ROUTING_MSM_ITEM, msmVo);
        }


    }

    @Override
    public Map<String, Object> getCountMap(OrderCountQueryVo orderCountQueryVo) {
      Map<String,Object> map =new HashMap<>();
        List<OrderCountVo> orderCountVos = baseMapper.selectOrderCount(orderCountQueryVo);
        //日期列表
        List<String> dateList = orderCountVos.stream().map(OrderCountVo::getReserveDate).collect(Collectors.toList());
        //统计列表
        List<Integer> countList = orderCountVos.stream().map(OrderCountVo::getCount).collect(Collectors.toList());
        map.put("dateList", dateList);
        map.put("countList", countList);
        return map;
    }

    @Override
    public IPage<OrderInfo> selectPage(Page<OrderInfo> pageParam, OrderQueryVo orderQueryVo) {
        QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();

        if(orderQueryVo!=null){
            Long userId = orderQueryVo.getUserId();
            if(!StringUtils.isEmpty(userId)){
                queryWrapper.eq("user_id",userId);
            }
            Long patientId = orderQueryVo.getPatientId();
            if(!StringUtils.isEmpty(patientId)){
                queryWrapper.eq("patient_id",patientId);
            }
            String orderStatus = orderQueryVo.getOrderStatus();
            if(!StringUtils.isEmpty(orderStatus)){
                queryWrapper.eq("order_status",orderStatus);
            }

            //其它

        }

        this.page(pageParam, queryWrapper);

        pageParam.getRecords().forEach(orderInfo -> {
            this.packOrderInfo(orderInfo);
        });

        return pageParam;
    }

    /**
     *  因为页面要显示 订单的状态是支付中  还是支付完成
     * @param orderInfo
     * @return
     */
    private OrderInfo packOrderInfo(OrderInfo orderInfo) {
          orderInfo.getParam().put("orderStatusString", OrderStatusEnum.getStatusNameByStatus(orderInfo.getOrderStatus()));
          return  orderInfo;
    }
}

